"""
@Author: li
@Email: lijianqiao2906@live.com
@FileTime: 2025/07/16 00:00:00
@Docs: 监控和审计模块
"""

import time
from datetime import datetime
from functools import wraps
from typing import Any

from app.utils.logger import logger


class PerformanceMonitor:
    """性能监控器"""

    def __init__(self):
        self.metrics = {}

    def track_operation(
        self, operation_name: str, duration: float, success: bool = True, error_message: str | None = None
    ):
        """跟踪操作性能"""
        if operation_name not in self.metrics:
            self.metrics[operation_name] = {
                "total_calls": 0,
                "total_duration": 0.0,
                "success_count": 0,
                "error_count": 0,
                "last_call": None,
                "errors": [],
            }

        metric = self.metrics[operation_name]
        metric["total_calls"] += 1
        metric["total_duration"] += duration
        metric["last_call"] = datetime.now()

        if success:
            metric["success_count"] += 1
        else:
            metric["error_count"] += 1
            if error_message:
                metric["errors"].append({"message": error_message, "timestamp": datetime.now()})

        # 保留最近10个错误
        if len(metric["errors"]) > 10:
            metric["errors"] = metric["errors"][-10:]

    def get_metrics(self, operation_name: str | None = None) -> dict[str, Any]:
        """获取性能指标"""
        if operation_name:
            return self.metrics.get(operation_name, {})
        return self.metrics

    def get_average_duration(self, operation_name: str) -> float | None:
        """获取平均操作时间"""
        metric = self.metrics.get(operation_name)
        if metric and metric["total_calls"] > 0:
            return metric["total_duration"] / metric["total_calls"]
        return None

    def get_success_rate(self, operation_name: str) -> float | None:
        """获取成功率"""
        metric = self.metrics.get(operation_name)
        if metric and metric["total_calls"] > 0:
            return (metric["success_count"] / metric["total_calls"]) * 100
        return None


class AuditLogger:
    """审计日志器"""

    def __init__(self):
        self.audit_log = []
        self.max_log_size = 1000

    def log_operation(
        self,
        operation: str,
        entity: str,
        entity_id: str,
        old_values: dict[str, Any] | None = None,
        new_values: dict[str, Any] | None = None,
        user: str | None = None,
        ip_address: str | None = None,
    ):
        """记录操作审计日志"""
        audit_entry = {
            "timestamp": datetime.now(),
            "operation": operation,
            "entity": entity,
            "entity_id": entity_id,
            "old_values": old_values,
            "new_values": new_values,
            "user": user or "system",
            "ip_address": ip_address,
            "id": len(self.audit_log) + 1,
        }

        self.audit_log.append(audit_entry)

        # 限制日志大小
        if len(self.audit_log) > self.max_log_size:
            self.audit_log = self.audit_log[-self.max_log_size :]

        # 记录到应用日志
        logger.info(f"AUDIT: {operation} {entity} {entity_id} by {user or 'system'}")

    def get_audit_log(self, entity: str | None = None, operation: str | None = None, limit: int = 100) -> list:
        """获取审计日志"""
        filtered_logs = self.audit_log

        if entity:
            filtered_logs = [log for log in filtered_logs if log["entity"] == entity]

        if operation:
            filtered_logs = [log for log in filtered_logs if log["operation"] == operation]

        return filtered_logs[-limit:]

    def get_recent_operations(self, entity_id: str, limit: int = 10) -> list:
        """获取实体的最近操作"""
        return [log for log in self.audit_log if log["entity_id"] == entity_id][-limit:]


def monitor_performance(operation_name: str):
    """性能监控装饰器"""

    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            start_time = time.time()
            success = True
            error_message = None

            try:
                result = await func(*args, **kwargs)
                return result
            except Exception as e:
                success = False
                error_message = str(e)
                raise
            finally:
                duration = time.time() - start_time
                performance_monitor.track_operation(operation_name, duration, success, error_message)

        return wrapper

    return decorator


def audit_operation(operation: str, entity: str):
    """审计操作装饰器"""

    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            entity_id = None
            old_values = None

            # 尝试从参数中提取实体ID
            if args:
                for arg in args:
                    if hasattr(arg, "id"):
                        entity_id = str(arg.id)
                        break
                    elif isinstance(arg, str) and len(arg) == 36:  # UUID
                        entity_id = arg
                        break

            # 记录旧值（如果是更新操作）
            if operation in ["update", "delete"] and entity_id:
                try:
                    # 这里需要根据具体实体获取旧值
                    old_values = {}  # 需要实现具体逻辑
                except Exception:
                    pass

            try:
                result = await func(*args, **kwargs)

                # 记录新值
                new_values = None
                if result and hasattr(result, "model_dump"):
                    new_values = result.model_dump()

                audit_logger.log_operation(
                    operation=operation,
                    entity=entity,
                    entity_id=entity_id or "unknown",
                    old_values=old_values,
                    new_values=new_values,
                )

                return result
            except Exception:
                audit_logger.log_operation(
                    operation=f"{operation}_failed",
                    entity=entity,
                    entity_id=entity_id or "unknown",
                    old_values=old_values,
                )
                raise

        return wrapper

    return decorator


# 全局监控器实例
performance_monitor = PerformanceMonitor()
audit_logger = AuditLogger()


# 健康检查函数
def get_system_health() -> dict[str, Any]:
    """获取系统健康状态"""
    from datetime import datetime

    health_status = {
        "timestamp": datetime.now(),
        "status": "healthy",
        "performance": {
            "total_operations": sum(m["total_calls"] for m in performance_monitor.metrics.values()),
            "average_response_time": 0,
            "success_rate": 0,
        },
        "audit": {
            "total_logs": len(audit_logger.audit_log),
            "recent_operations": len(audit_logger.get_audit_log(limit=10)),
        },
    }

    # 计算平均响应时间
    total_ops = 0
    total_duration = 0
    total_success = 0

    for metric in performance_monitor.metrics.values():
        total_ops += metric["total_calls"]
        total_duration += metric["total_duration"]
        total_success += metric["success_count"]

    if total_ops > 0:
        health_status["performance"]["average_response_time"] = total_duration / total_ops
        health_status["performance"]["success_rate"] = (total_success / total_ops) * 100

    return health_status
